#ifndef _BARTER_SERVER_HANDLE_H_
#define _BARTER_SERVER_HANDLE_H_

template<typename T> class Handle
{
private:
	struct Reference
	{
		int NumRefs;
		T* Handle;
	};
	Reference* Ref;
	void New()
	{
		Ref = new Reference;
		Ref->NumRefs = 0;
		Ref->Handle = NULL;
	}
	void Close()
	{
		if (Ref && Ref->Handle)
		{
			delete Ref->Handle;
		}
		if (Ref)
		{
			delete Ref;
		}
	}
public:
	Handle()
	{
		Ref = NULL;
	}
	Handle(T d)
	{
		New();
		*(Ref->Handle) = d;
	}
	Handle(T& d)
	{
		New();
		*(Ref->Handle) = d;
	}
	Handle(T* d)
	{
		New();
		*(Ref->Handle) = *d;
	}
	Handle(const Handle& h)
	{
		Ref = h.Ref;
		if (!IsEmpty())
		{
			Ref->NumRefs++;
		}
	}
	Handle(Handle& h)
	{
		Ref = h.Ref;
		if (!IsEmpty())
		{
			Ref->NumRefs++;
		}
	}
	~Handle()
	{
		Release();
	}
	T operator*() const
	{
		T dummy;
		if (!IsEmpty())
		{
			return *(Ref->Handle);
		}
		return dummy;
	}
	T& operator*()
	{
		T dummy;
		if (!IsEmpty())
		{
			return *(Ref->Handle);
		}
		return dummy;
	}
	T* operator->()
	{
		if (IsEmpty())
		{
			return NULL;
		}
		return Ref->Handle;
	}
	Handle& operator=(Handle& h)
	{
		Release();
		Ref = h.Ref;
		if (!IsEmpty())
		{
			Ref->NumRefs++;
		}
		return *this;
	}
	Handle& operator=(const Handle& h)
	{
		Release();
		Ref = h.Ref;
		if (!IsEmpty())
		{
			Ref->NumRefs++;
		}
		return *this;
	}
	Handle& operator=(T d)
	{
		Release();
		New();
		*(Ref->Handle) = d;
		return *this;
	}
	Handle& operator=(T& d)
	{
		Release();
		New();
		*(Ref->Handle) = d;
		return *this;
	}
	Handle& operator=(T* d)
	{
		Release();
		New();
		*(Ref->Handle) = *d;
		return *this;
	}
	bool IsEmpty() const
	{
		return Ref == NULL;
	}
	void Release()
	{
		if (!IsEmpty())
		{
			Ref->NumRefs--;
			if (Ref->NumRefs <= 0)
			{
				Close();
			}
		}
	}
};

#endif // _BARTER_SERVER_HANDLE_H_
